#include "mircrophoneiodevice.h"
#include <QDateTime>
#include <QDebug>
#include "utils/signalcenter.h"
#include "utils/util.h"
MircrophoneIODevice::MircrophoneIODevice(QObject *parent)
    : QIODevice{parent}
{}

void MircrophoneIODevice::start()
{
    QIODevice::open(QIODevice::ReadWrite);
}

void MircrophoneIODevice::stop()
{
    QMutexLocker locker(&mutex);
    QIODevice::close();
    buffer.clear();
}

bool MircrophoneIODevice::bufferIsEmpty()
{
    return buffer.isEmpty();
}

void MircrophoneIODevice::computeAudioData(char *data, qint64 bytesRead)
{
    const SampleType *samples = reinterpret_cast<const SampleType *>(data);
    int totalSamples = bytesRead / sizeof(SampleType); // 样本总数
    int frameCount = totalSamples / 2;                 // 每帧包含 2 个声道的样本
    // qDebug() << "totalSamples count: " << totalSamples;
    // 3. 统计左右声道的音量数据
    double sumSquareLeft = 0.0;
    double sumSquareRight = 0.0;
    SampleType peakLeft = 0.0f;
    SampleType peakRight = 0.0f;

    // 4. 遍历所有的帧，计算左声道和右声道的 RMS 和峰值
    for (int i = 0; i < frameCount; ++i) {
        SampleType leftSample = std::clamp(samples[2 * i], -1.0f, 1.0f);      // 左声道
        SampleType rightSample = std::clamp(samples[2 * i + 1], -1.0f, 1.0f); // 右声道

        // 计算左声道的RMS和峰值
        sumSquareLeft += leftSample * leftSample;            // 平方和
        peakLeft = std::max(peakLeft, std::abs(leftSample)); // 取样本的绝对最大值

        // 计算右声道的RMS和峰值
        sumSquareRight += rightSample * rightSample;
        peakRight = std::max(peakRight, std::abs(rightSample));
    }

    // 5. 计算 RMS (均方根)，如果数据出错的话，RMS 可能为 0，如果样本中全部是 0，log10(0) 会产生 -inf (负无穷大)。
    //因此需要设定一个最小值是0.00001
    double rmsLeft = std::max(0.00001, std::sqrt(sumSquareLeft / frameCount));
    double rmsRight = std::max(0.00001, std::sqrt(sumSquareRight / frameCount));

    // 6. 计算 dBFS（参考值为 1.0）
    double dBFSLeft = 20.0 * std::log10(rmsLeft);
    double dBFSRight = 20.0 * std::log10(rmsRight);

    //合并dBFS和RMS
    double avgRMS = (rmsLeft + rmsRight) / 2.0;
    double avgdBFS = (dBFSLeft + dBFSRight) / 2.0;
    // 7. 打印音量数据
    // qDebug() << "Left Peak:" << peakLeft << "Right Peak:" << peakRight << "RMS Left:" << rmsLeft
    //          << "RMS Right:" << rmsRight << "dBFS Left:" << dBFSLeft << "dBFS Right:" << dBFSRight;
    float Value = std::clamp(static_cast<int>((1 + avgdBFS / 60.0) * 100), 0, 100);
    if (Value > 0 && emitSign) {
        emit SignalCenter::instance().audioDataComputeCompleted(Value, INPUTLEVEL);
        emitSign = false;
    } else {
        emit SignalCenter::instance().clearProBarVolume(INPUTLEVEL);
        emitSign = true;
    }
    Q_UNUSED(avgRMS);
}

qint64 MircrophoneIODevice::readData(char *data, qint64 maxSize)
{
    QMutexLocker locker(&mutex);

    if (buffer.isEmpty()) {
        //判断设备打没打开
        if (!QIODevice::isOpen()) {
            qWarning() << "MircrophoneIODevice is not open";
        }
        condition.wait(&mutex); //释放说并阻塞
    }

    //只会复制能复制的数据，当数据比maxSize大时，复制maxsize的数据，否则复制全部的
    qint64 len = qMin(qint64(buffer.size()), maxSize);
    memcpy(data, buffer.constData(), len);
    buffer.remove(0, len);
    qDebug() << "Read" << len << "bytes from MircrophoneIODevice's buffer at"
             << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
    globalThreadPool->start(std::bind(&MircrophoneIODevice::computeAudioData, this, data, len));
    return len;
}

qint64 MircrophoneIODevice::writeData(const char *data, qint64 maxSize)
{
    QMutexLocker locker(&mutex);

    buffer.append(data, maxSize);
    condition.wakeAll();
    qDebug() << "Write" << maxSize << "bytes to MircrophoneIODevice's buffer at"
             << QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
    // qDebug() << buffer.size();
    return maxSize;
}

qint64 MircrophoneIODevice::bytesAvailable() const
{
    QMutexLocker locker(&mutex);
    // qDebug() << "buffer.size():" << buffer.size();
    return buffer.size() + QIODevice::bytesAvailable();
}
